package cn.org.rookie.jeesdp.core.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类，提供日期格式化、解析和计算等常用方法
 *
 * @author LHT
 */
public abstract class DateUtils {

    /**
     * 时分秒格式：HH:mm:ss
     */
    public static final String HH_MM_SS = "HH:mm:ss";

    /**
     * 年月日格式：yyyy-MM-dd
     */
    public static final String YYYY_MM_DD = "yyyy-MM-dd";

    /**
     * 紧凑日期时间格式：yyyyMMddHHmmss
     */
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    /**
     * 标准日期时间格式：yyyy-MM-dd HH:mm:ss
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 带毫秒的日期时间格式：yyyy-MM-dd HH:mm:ss.SSS
     */
    public static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

    /**
     * ISO格式日期时间：yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
     */
    public static final String YYYY_MM_DD_T_HH_MM_SS_SSS_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    /**
     * 一分钟的毫秒数：60000L
     */
    public static final long MINUTE_PER_MILLIS = 60000L;

    /**
     * 一小时的毫秒数：3600000L
     */
    public static final long HOUR_PER_MILLIS = 3600000L;

    /**
     * 一天的毫秒数：86400000L
     */
    public static final long DAY_PER_MILLIS = 86400000L;

    /**
     * 线程不安全的日期格式化对象，仅用于工具类内部
     */
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat();

    /**
     * 获取当前时间的标准格式字符串
     *
     * @return 当前时间的yyyy-MM-dd HH:mm:ss格式字符串
     */
    public static String now() {
        return format(new Date(), YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取指定格式的当前时间字符串
     *
     * @param pattern 日期格式模式
     * @return 当前时间的指定格式字符串
     */
    public static String now(String pattern) {
        return format(new Date(), pattern);
    }

    /**
     * 将日期格式化为标准格式字符串
     *
     * @param date 日期对象
     * @return yyyy-MM-dd HH:mm:ss格式的日期字符串
     */
    public static String format(Date date) {
        return format(date, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 将日期格式化为指定格式字符串
     *
     * @param date    日期对象
     * @param pattern 日期格式模式
     * @return 指定格式的日期字符串
     */
    public static String format(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        DATE_FORMAT.applyPattern(pattern);
        return DATE_FORMAT.format(date);
    }

    /**
     * 将标准格式字符串解析为日期
     *
     * @param date yyyy-MM-dd HH:mm:ss格式的日期字符串
     * @return 日期对象
     * @throws RuntimeException 当字符串格式不正确时抛出
     */
    public static Date parse(String date) {
        return parse(date, YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 将指定格式字符串解析为日期
     *
     * @param date    日期字符串
     * @param pattern 日期格式模式
     * @return 日期对象
     * @throws RuntimeException 当字符串格式不正确时抛出
     */
    public static Date parse(String date, String pattern) {
        if (date == null || date.isEmpty()) {
            return null;
        }
        try {
            DATE_FORMAT.applyPattern(pattern);
            return DATE_FORMAT.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException("日期解析失败: " + date + ", 格式: " + pattern, e);
        }
    }

    /**
     * 对日期进行加减运算
     *
     * @param date   原始日期
     * @param field  日期字段，如Calendar.YEAR, Calendar.MONTH等
     * @param amount 加减的数量，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date add(Date date, int field, int amount) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 对指定日期进行年份加减
     *
     * @param date   原始日期
     * @param amount 加减的年数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addYear(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    /**
     * 对当前日期进行年份加减
     *
     * @param amount 加减的年数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addYear(int amount) {
        return addYear(new Date(), amount);
    }

    /**
     * 对指定日期进行月份加减
     *
     * @param date   原始日期
     * @param amount 加减的月数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addMonth(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    /**
     * 对当前日期进行月份加减
     *
     * @param amount 加减的月数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addMonth(int amount) {
        return addMonth(new Date(), amount);
    }

    /**
     * 对指定日期进行天数加减
     *
     * @param date   原始日期
     * @param amount 加减的天数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addDay(Date date, int amount) {
        return add(date, Calendar.DAY_OF_YEAR, amount);
    }

    /**
     * 对当前日期进行天数加减
     *
     * @param amount 加减的天数，正数为加，负数为减
     * @return 计算后的日期
     */
    public static Date addDay(int amount) {
        return addDay(new Date(), amount);
    }

}
